# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Helper script to deploy the cq_stats app to our appengine instances."""

from __future__ import print_function

import os
import time

from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import osutils


APP_INSTANCE_DEBUG = 'debug'
APP_INSTANCE_PROD = 'prod'

APP_INSTANCE_NAME = {
    APP_INSTANCE_DEBUG: 'google.com:chromiumos-build-annotator-dbg',
    APP_INSTANCE_PROD: 'google.com:chromiumos-build-annotator',
}
APP_INSTANCE_CIDB = {
    APP_INSTANCE_DEBUG: 'debug-cidb',
    APP_INSTANCE_PROD: 'cidb',
}


def _GetParser():
  """Get parser for deploy_app cli.

  Returns:
    commandline.ArgumentParser object to parse the commandline args.
  """
  parser = commandline.ArgumentParser()
  parser.add_argument('instance', type=str,
                      choices=(APP_INSTANCE_DEBUG, APP_INSTANCE_PROD),
                      help='The app instance to deploy to')
  parser.add_argument('--secret-key', type=str, required=True,
                      help='The secret key to sign django cookies.')
  return parser


def _GetDeploySettings(options):
  """The autogenerated part of django settings.

  Returns:
    python "code" as str to be written to the settings file.
  """
  content = [
      '# DO NOT EDIT! Autogenerated by %s.' % os.path.basename(__file__),
      'DEBUG = False',
      'TEMPLATE_DEBUG = False',
      'SECRET_KEY = "%s"' % options.secret_key,
      'CIDB_PROJECT_NAME = "cosmic-strategy-646"',
      'CIDB_INSTANCE_NAME = "%s"' % APP_INSTANCE_CIDB[options.instance],
  ]
  return '\n'.join(content)


def _DeployApp(basedir):
  """Deploy the prepared app from basedir.

  Args:
    basedir: The base directory where the app has already been prepped.
  """
  cros_build_lib.RunCommand(
      ['./ae_shell', 'cq_stats', '--',
       'python', 'cq_stats/manage.py', 'collectstatic', '--noinput'],
      cwd=basedir)

  # Remove sensetive files that are needed to run tools locally to prepare the
  # deploy directory, but that we don't want to push to AE.
  cidb_cred_path = os.path.join(basedir, 'cq_stats', 'annotator_cidb_creds')
  osutils.SafeUnlink(os.path.join(cidb_cred_path, 'client-cert.pem'))
  osutils.SafeUnlink(os.path.join(cidb_cred_path, 'client-key.pem'))
  osutils.SafeUnlink(os.path.join(cidb_cred_path, 'server-ca.pem'))
  cros_build_lib.RunCommand(
      ['./ae_shell', 'cq_stats', '--',
       'appcfg.py', '--oauth2', 'update', 'cq_stats'],
      cwd=basedir)


def _Hang(tempdir):
  """How else will you ever work on this script?

  Args:
    tempdir: The directory prepared for deploying the app.
  """
  logging.info('All the real stuff\'s done. Tempdir: %s', tempdir)
  while True:
    logging.info('Sleeping... Hit Ctrl-C to exit.')
    time.sleep(30)


def main(argv):
  parser = _GetParser()
  options = parser.parse_args(argv)
  options.Freeze()

  with osutils.TempDir() as tempdir:
    # This is rsync in 'archive' mode, but symlinks are followed to copy actual
    # files/directories.
    rsync_cmd = ['rsync', '-qrLgotD', '--exclude=\'*/*.pyc\'']
    chromite_dir = os.path.dirname(
        os.path.dirname(
            os.path.dirname(
                os.path.abspath(__file__))))

    cmd = rsync_cmd + [
        'chromite/appengine/', tempdir,
        '--exclude=google_appengine_*',
    ]
    cros_build_lib.RunCommand(cmd, cwd=os.path.dirname(chromite_dir))

    cmd = rsync_cmd + [
        'chromite', os.path.join(tempdir, 'cq_stats'),
        '--exclude=appengine',
        '--exclude=third_party',
        '--exclude=ssh_keys',
        '--exclude=contrib',
        '--exclude=.git',
    ]
    cros_build_lib.RunCommand(cmd, cwd=os.path.dirname(chromite_dir))

    osutils.WriteFile(os.path.join(tempdir, 'cq_stats', 'cq_stats',
                                   'deploy_settings.py'),
                      _GetDeploySettings(options))

    # update the instance we're updating.
    # Use absolute path. Let's not update sourcedir by mistake.
    app_yaml_path = os.path.join(tempdir, 'cq_stats', 'app.yaml')
    regex = (r's/^application:[ \t]*[a-zA-Z0-9_-\.:]\+[ \t]*$'
             '/application: %s/')
    cmd = [
        'sed', '-i',
        '-e', regex % APP_INSTANCE_NAME[options.instance],
        app_yaml_path,
    ]
    cros_build_lib.RunCommand(cmd, cwd=tempdir)

    _DeployApp(tempdir)
    # _Hang(tempdir)
